
-- ======================================================
-- 刷新外交/贸易当前领袖对象
local SelectedPlayerID = -1
local SelectedLeaderType = ""
local SelectedLeader2DAni = {}
function UpdateSelectedLeader(PlayerID)
	SelectedLeaderType = PlayerConfigurations[PlayerID]:GetLeaderTypeName()
	SelectedLeader2DAni = Leader2DAni[SelectedLeaderType]
	print("UpdateSelectedLeader:",PlayerID,"Name:",SelectedLeaderType);
end
--DiploScene_RefreshOverviewRows
LuaEvents.DiploScene_LeaderSelect.Add(UpdateSelectedLeader);
function UpdateSelectedLeader2(PlayerID)
    SelectedPlayerID = PlayerID;
	SelectedLeaderType = PlayerConfigurations[PlayerID]:GetLeaderTypeName();
	SelectedLeader2DAni = Leader2DAni[SelectedLeaderType];

	print("UpdateSelectedLeader2:",PlayerID,"Name:",SelectedLeaderType);
end
--DiploScene_RefreshOverviewRows
LuaEvents.DiploScene_RefreshOverviewRows.Add(UpdateSelectedLeader2);
-- ======================================================
function GetSelectedLeaderType()
	return SelectedLeaderType
end
LuaEvents.PK_GetSelectedLeaderType.Add(GetSelectedLeaderType);

-- ===========================================================================
--	VARIABLES
-- ===========================================================================
-- 动画队列
ms_LeaderAnimationQueue		= {};
-- 背景效果队列
ms_BackgroundEffectQueue	= {};
-- 是否是初始动画 
ms_bInitialAnimtion			= true;
-- 导者是否可见(这里的可见是是否在外交界面可显示)
ms_bLeaderIsVisible			= false;

------------------------------------------------------------------------------
-- 用于更新领导者动画队列的函数
function LeaderSupport_UpdateAnimationQueue()
    print("LeaderSupport_UpdateAnimationQueue")
    -- 检查领导者是否可见
    -- 检查领导者是否可见、动画队列是否存在、动画队列的序列是否为空以及序列中是否有动画
    if ms_bLeaderIsVisible and ms_LeaderAnimationQueue ~= nil and ms_LeaderAnimationQueue.Sequence ~= nil and table.count(ms_LeaderAnimationQueue.Sequence) > 0 then
        -- 如果是初始动画
		print("ms_bLeaderIsVisible:true")
        if ms_bInitialAnimtion then
            ms_bInitialAnimtion = false;
			print("ms_bInitialAnimtion:false")
            -- 如果存在特定的初始动画，此时是真初始动画
            if (ms_LeaderAnimationQueue.Initial ~= nil and ms_LeaderAnimationQueue.Initial ~= "") then
                -- 播放特定的初始动画，设置混合时间为0.0秒
                
				print("PPK有初播放:",ms_LeaderAnimationQueue.Initial)
                UI.PlayLeaderAnimation(ms_LeaderAnimationQueue.Initial, {BlendTime = 0.0});
                -- 立即播放序列中的下一个动画，因为强制的初始动画可能是循环动画，永远不会完成
				print("PPK初后播放:",ms_LeaderAnimationQueue.Sequence[1])
                UI.PlayLeaderAnimation(ms_LeaderAnimationQueue.Sequence[1]);
                -- 从动画队列中移除已播放的特定的初始动画
                ms_LeaderAnimationQueue.Initial = nil;
            else
                -- 播放序列中的下一个动画，设置混合时间为0.0秒
				print("PPK播放:",ms_LeaderAnimationQueue.Sequence[1])
                UI.PlayLeaderAnimation(ms_LeaderAnimationQueue.Sequence[1], {BlendTime = 0.0});
            end
        else
            -- 播放序列中的下一个动画
			print("ms_bInitialAnimtion:true")
			print("PPK不初播放:",ms_LeaderAnimationQueue.Sequence[1])
            UI.PlayLeaderAnimation(ms_LeaderAnimationQueue.Sequence[1]);
        end
        -- 从序列中移除已播放的动画
        table.remove(ms_LeaderAnimationQueue.Sequence, 1);
        return;
    end
	print("ms_bLeaderIsVisible:false")
end
LuaEvents.PK_UpdateAnimationQueue.Add(LeaderSupport_UpdateAnimationQueue);
------------------------------------------------------------------------------
-- 用于更新场景特效队列函数
function LeaderSupport_UpdateSceneEffectQueue()
    print("LeaderSupport_UpdateSceneEffectQueue")
    -- 检查领导者是否可见且背景特效队列中是否有元素
    if ms_bLeaderIsVisible and (table.count(ms_BackgroundEffectQueue) > 0) then
        -- 播放第一个背景特效
        UI.PlayLeaderSceneEffect(ms_BackgroundEffectQueue[1]);
        -- 从队列中移除已播放的背景特效（移除已播放的元素，即索引为1的元素。）
        table.remove(ms_BackgroundEffectQueue, 1);
    end
end

------------------------------------------------------------------------------


------------------------------------------------------------------------------
-- 从查询结果获取领导者动画序列
function GetLeaderAnimationSequenceFromQuery(q, kOutputTable : table, leaderMood)
    print("GetLeaderAnimationSequenceFromQuery")
    -- 遍历查询结果
    for i, row in ipairs(q) do		-- 应该只有一条结果
        local initialAnimation = row.Initial;

        -- 如果存在初始动画
        if (initialAnimation ~= nil) then
            -- 根据领导者的情绪替换动画名称中的占位符
			print("PPKinitialAnimation0:",initialAnimation)
            if (leaderMood ~= nil) then
				print("PPKinitialAnimation1:",initialAnimation)
                if (leaderMood == DiplomacyMoodTypes.HAPPY) then 
                    initialAnimation = string.gsub(initialAnimation, "%$%(MOOD%)","HAPPY");
                elseif (leaderMood == DiplomacyMoodTypes.NEUTRAL) then
                    initialAnimation = string.gsub(initialAnimation, "%$%(MOOD%)","NEUTRAL");
                elseif (leaderMood == DiplomacyMoodTypes.UNHAPPY) then
                    initialAnimation = string.gsub(initialAnimation, "%$%(MOOD%)","UNHAPPY");
                end
				print("PPKinitialAnimation2:",initialAnimation)
            end
        end
        if row.Name == "ENRAGED" then
			initialAnimation = string.gsub(initialAnimation, "%$%(MOOD%)","HAPPY");
		end
        -- 将初始动画和动画序列存入输出表
        kOutputTable.Initial = initialAnimation;
        kOutputTable.Sequence = {};
        -- 解析动画序列字符串，将每个动画添加到序列中	
        for anim in string.gmatch(row.Sequence, "([%w_]+)") do
			print("PPKSequence.anim:",anim)			
            table.insert(kOutputTable.Sequence, anim);
        end
        
        local initial2 = row.Initial;
        if row.Initial == nil then
			initial2 = "nil";
        end	
		print("LeaderAnimations表: Name: " .. row.Name ..", Leader: " .. row.Leader ..", Initial: " .. initial2 ..", Sequence: " .. row.Sequence)
    end

    -- 返回动画序列是否非空
    if (kOutputTable.Sequence ~= nil) then
        return table.count(kOutputTable.Sequence) > 0;
    else
        return false;
    end
end

------------------------------------------------------------------------------
-- 获取领导者动画序列
function GetLeaderAnimationSequence(leaderName : string, sequenceName : string, leaderMood )
    print("GetLeaderAnimationSequence")
    local kOutputTable = {};
    print("PPKGetLeade " ..leaderName, sequenceName, leaderMood)
    -- 查询数据库获取动画序列
    local q = DB.Query("SELECT Name, Leader, Sequence, Initial from LeaderAnimations WHERE Leader = ? AND Name = ?", leaderName, sequenceName);
    if (not GetLeaderAnimationSequenceFromQuery(q, kOutputTable, leaderMood)) then
		print("PPKGetLeade2")	
        q = DB.Query("SELECT Name, Leader, Sequence, Initial from LeaderAnimations WHERE Leader = 'ANY' AND Name = ?", sequenceName);
        GetLeaderAnimationSequenceFromQuery(q, kOutputTable, leaderMood);
    end

    return kOutputTable;
end

------------------------------------------------------------------------------
-- 添加领导者动画序列到动画队列
function LeaderSupport_QueueAnimationSequence( leaderName: string, sequenceName : string, leaderMood )
    print("LeaderSupport_QueueAnimationSequence")
    local kSequence = GetLeaderAnimationSequence(leaderName, sequenceName, leaderMood);
    if (kSequence ~= nil) then
        -- 当前序列为空或已完成？
        if (ms_LeaderAnimationQueue.Sequence == nil or #ms_LeaderAnimationQueue.Sequence == 0) then
            ms_LeaderAnimationQueue = kSequence;
            -- 更新领导者动画队列
			print("添加领导者:UpdateAnimationQueue")
            LeaderSupport_UpdateAnimationQueue();
        else
            -- 上一个序列仍有动画待播放
            if (kSequence.Sequence ~= nil) then				
                -- 将新动画添加到末尾会很好，但是最后一个动画是否为循环？
                -- 如果是，则永远不会播放新序列的动画，将永远不会得到我们想要的动画，故不添加
                -- 所以，将新序列添加至队列末尾，等待当前动画播放完毕后启动
                ms_LeaderAnimationQueue = kSequence;
                if (ms_LeaderAnimationQueue.Initial ~= nil and ms_LeaderAnimationQueue.Initial ~= "") then
                    -- 表示为初始动画
                    ms_bInitialAnimtion = true;	
                end
            end
        end
    end
end
LuaEvents.PK_QueueAnimationSequence.Add(LeaderSupport_QueueAnimationSequence);
------------------------------------------------------------------------------
-- 添加背景特效到特效队列
function LeaderSupport_QueueSceneEffect( effectName : string )
    print("LeaderSupport_QueueSceneEffect")
    -- 如果特效名称非空，则加入背景特效队列
    if (effectName ~= nil) then
        table.insert(ms_BackgroundEffectQueue, effectName);
        -- 更新场景特效队列
        LeaderSupport_UpdateSceneEffectQueue();
    end
end

------------------------------------------------------------------------------
-- 初始化领导者支持LeaderSupport.lua的参数
function LeaderSupport_Initialize()
    print("LeaderSupport_Initialize")
    ms_bLeaderIsVisible = false;
    ms_bInitialAnimtion = true;
    ms_LeaderAnimationQueue = {};
end
LuaEvents.PK_Initialize.Add(LeaderSupport_Initialize);
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- 当领导者加载完成时调用播放领袖动画
function LeaderSupport_OnLeaderLoaded()
	print("播放领导者:UpdateAnimationQueue")
    ms_bLeaderIsVisible = true;
    -- 播放领导者动画队列
    LeaderSupport_UpdateAnimationQueue();
    -- 播放场景特效队列
    LeaderSupport_UpdateSceneEffectQueue();
end
LuaEvents.PK_OnLeaderLoaded.Add(LeaderSupport_OnLeaderLoaded);
------------------------------------------------------------------------------
-- 检查领导者是否可见
function LeaderSupport_IsLeaderVisible()
    print("LeaderSupport_IsLeaderVisible")
    return ms_bLeaderIsVisible;
end

------------------------------------------------------------------------------
-- 清除初始动画状态
function LeaderSupport_ClearInitialAnimationState()
    print("LeaderSupport_ClearInitialAnimationState")
    ms_bInitialAnimtion = true;
end
LuaEvents.PK_ClearInitialAnimationState.Add(LeaderSupport_ClearInitialAnimationState);

-- ======================================================
-- 在lua根据sql数据库的表，构造相关表
--local DeBugs = false;
local DeBugs = true;
local D1 = "有字符串不符合要求，应当为数值，字母，下划线，分号组成的，且分号不能位于开头或结尾，其中分号是用于分隔"
local D2 = "有字符串不符合要求，应当为数值，字母，下划线，组成的，不包含分号"
function DeBugs(t1, t2, t3, t4)
	if not DeBugs then return; end
	print("检查" ..t1 "表'" ..t2 .."',它的" ..t3 "设置" ..t4);
end
function StringDeBugs(t, t1, t2, t3, t4)
	if not string.match(t, "^[%w_;]+$") and string.sub(str, 1, 1) == ";" and string.sub(str, -1, -1) == ";" then
		DeBugs(t1, t2, t3, t4)
	end
end
function StringDeBugs2(t, t1, t2, t3, t4)
    if not string.match(t, "^[%w_]+$") then
        DeBugs(t1, t2, t3, t4)
    end
end
Leader2DAni = {}
AniIDs = {}
function CreateLeader2DAni()

    -- 获取当前存活的所有主要玩家领袖类型
	local kAliveLeaders = PlayerManager.GetAliveMajorIDs();
	for k, PlayerID in pairs(kAliveLeaders) do
        -- 将每个存活领袖的动画信息初始化为空表
		Leader2DAni[PlayerConfigurations[PlayerID]:GetLeaderTypeName()] = {}
	end
		
    -- 遍历所有领袖2D动画信息
	for row in GameInfo.Leader2DAnimations() do
		local LeaderAni = Leader2DAni[row.LeaderType];
		if LeaderAni then
            -- 初始化 Name 和 Mode
			if not LeaderAni[row.Name] then LeaderAni[row.Name] = {Mode  = row.Mode, AllAniIDs = {}} end
			local AllAni = LeaderAni[row.Name].AllAniIDs;
			
			-- 检查AllAniIDs
			StringDeBugs(row.AllAniIDs, "Leader2DAnimationsrow", "LeaderType=" ..row.LeaderType .."-Name=" ..row.Name, "AllAniIDs", D1 .."AniID" )

            -- 解析并添加 AllAniIDs
            for AniID in string.gmatch(row.AllAniIDs, "([^;]+)") do
                table.insert(AllAni, AniID)
                AniIDs[AniID] = {}
            end
			
			-- 处理Occupy 皮一下，哈哈哈
			if row.Occupy then AllAni[0] = "PiPiKai"; end
			-- 如果SelectedLeader2DAni无表示该领袖没有2D动画，直接播放3D动画
			-- 如果SelectedLeader2DAni有，且AllAni[0] = "PiPiKai"那么随机到0则播放3D
		end
	end
end
-- 初始化数据结构
Leader2DAni = {}
AniIDs = {}

function CreateLeader2DAni()
    -- 获取当前存活的所有主要玩家领袖类型
    local kAliveLeaders = PlayerManager.GetAliveMajorIDs()
    
    for _, PlayerID in ipairs(kAliveLeaders) do
        -- 将每个存活领袖的动画信息初始化为空表
        Leader2DAni[PlayerConfigurations[PlayerID]:GetLeaderTypeName()] = {}
    end

    -- 遍历所有领袖2D动画信息
    for row in GameInfo.Leader2DAnimations() do
        local LeaderType = row.LeaderType
        local LeaderAni = Leader2DAni[LeaderType]

        if LeaderAni then
            -- 初始化 Name 和 Mode
            if not LeaderAni[row.Name] then
                LeaderAni[row.Name] = {
                    Mode = row.Mode,
                    AllAniIDs = {},
                }
            end
            local AllAni = LeaderAni[row.Name].AllAniIDs
            
            -- 解析并添加 AllAniIDs
            for AniID in string.gmatch(row.AllAniIDs, "([^;]+)") do
                table.insert(AllAni, AniID)
                AniIDs[AniID] = {}
            end

--[ ======================================================
-- 获取指定玩家与本地玩家的外交情绪
function GetPlayerMood()
    -- 获取玩家的外交AI对象
    local LocalPlayerID = Game.GetLocalPlayer()
    if LocalPlayerID == SelectedPlayerID then
        return DiplomacyMoodTypes.NEUTRAL;
    end

	local pPlayerDiplomaticAI = Players[SelectedPlayerID]:GetDiplomaticAI();
    -- 获取本地玩家与指定玩家的外交状态索引
	local iState : number = pPlayerDiplomaticAI:GetDiplomaticStateIndex();

    -- 由于数据库的顺序不能保证，所以通过哈希值来比较已知的外交状态
	local kStateEntry = GameInfo.DiplomaticStates[iState];
	local eState = kStateEntry.Hash;

    -- 判断外交状态，并返回相应的外交情绪
	if (eState == DiplomaticStates.ALLIED or eState == DiplomaticStates.DECLARED_FRIEND) then 
		return DiplomacyMoodTypes.HAPPY;
	end

	if (eState == DiplomaticStates.FRIENDLY or eState == DiplomaticStates.NEUTRAL or eState == DiplomaticStates.UNFRIENDLY) then 
		return DiplomacyMoodTypes.NEUTRAL;
	end

	if (eState == DiplomaticStates.DENOUNCED or eState == DiplomaticStates.WAR) then 
		return DiplomacyMoodTypes.UNHAPPY;
	end

    -- 如果没有匹配到任何已知的外交状态，返回中立情绪
	return DiplomacyMoodTypes.NEUTRAL;
end
function AniClipMood(AniClip)
    if not string.find(AniClip, "MOOD") then return AniClip; end
    local leaderMood = GetPlayerMood()
    if      (leaderMood == DiplomacyMoodTypes.HAPPY)    then return string.gsub(AniClip, "MOOD","HAPPY");
    elseif  (leaderMood == DiplomacyMoodTypes.NEUTRAL)  then return string.gsub(AniClip, "MOOD","NEUTRAL");
    elseif  (leaderMood == DiplomacyMoodTypes.UNHAPPY)  then return string.gsub(AniClip, "MOOD","UNHAPPY");
    end
end

function CreateAniIDs()

    for aniIDRow in GameInfo.AniIDs() do
        -- 获取并初始化大动画数据
        local AIDs = AniIDs[aniIDRow.AniID]
        if AIDs then
            -- 检查并处理Initial
            StringDeBugs2(aniIDRow.Initial, "AniIDs", "AniID=" .. aniIDRow.AniID, "Initial", D2)

            local InitialAni = GameInfo.Anis[aniIDRow.Initial]
            local SpeedTable = {}
            local addUniqueSpeed = function(Speed)
                for _, speed in pairs(SpeedTable) do
                    if speed == Speed then
                        return
                    end
                end
                table.insert(SpeedTable, Speed)
            end

            local key = 0
            for AniClipStr in string.gmatch(InitialAni.AllAniClips, "([^;]+)") do
                local Clip = GameInfo.AniClips[AniClipMood(AniClipStr)]
                if Clip.Speed <= 0 then
                    DeBugs("AniClips", AniClipStr, "Speed", "没有大于0")
                end
                addUniqueSpeed(Clip.Speed)
                for i = 1, Clip.Num do
                    key = key + 1
                    AIDs.Ani[key] = {
                        TName = Clip.TName .. "_" .. i,
                        StopTime = Clip.Speed
                    }
                end
            end

            -- 检查并处理Sequence
            StringDeBugs(aniIDRow.Sequence, "AniIDs", "AniID=" .. aniIDRow.AniID, "Sequence,", D1 .. "AniType")

            local lastAniType = false
            local AniTypeNum, AniTypeTotal = 0, string.gsub(aniIDRow.Sequence, ";", "") + 1
            for AniType in string.gmatch(aniIDRow.Sequence, "([^;]+)") do
                local Ani = GameInfo.Anis[AniType]
                AniTypeNum = AniTypeNum + 1
                if AniTypeNum == AniTypeTotal and Ani.Loop then
                    lastAniType = true
                end
                for AniClipStr in string.gmatch(Ani.AllAniClips, "([^;]+)") do
                    local Clip = GameInfo.AniClips[AniClipMood(AniClipStr)]
                    if Clip.Speed <= 0 then
                        DeBugs("AniClips", AniClipStr, "Speed", "没有大于0")
                    end
                    addUniqueSpeed(Clip.Speed)
                    for i = 1, AniClip.Num do
                        key = key + 1
                        if lastAniType then
                            lastAniType = false
                            AIDs.LoopKey = key
                        end
                        AIDs.Ani[key] = {
                            Name = AniClip.TName .. "_" .. i,
                            StopTime = Clip.Speed
                        }
                    end
                end
            end

            -- 定义通用处理函数
            local getMultiplierAndMinValue = function(num)
                local integerPart, decimalPart = math.modf(num)
                local minDecimalValue = 10 ^ (-math.abs(math.log10(decimalPart)))
                return minDecimalValue, (integerPart + decimalPart) * minDecimalValue
            end
            local gcd = function(x, y)
                repeat until y == 0
                local temp = x
                x = y
                y = temp % y
                return x
            end
            local gcdAndNormalize = function(a, b)
                local greatest_common_divisor = gcd(math.abs(a), math.abs(b))
                return a / greatest_common_divisor, b / greatest_common_divisor
            end
            local processQuotesAndAudios = function(dataName, delayTimeName, container)
                local containerData = AIDs[container]

                if row[dataName] then
                    containerData = {}
                    local dataTotal, delayTimeTotal = string.gsub(row[dataName], ";", "") + 1, string.gsub(row[delayTimeName], ";", "") + 1
                    if dataTotal ~= delayTimeTotal then
                        DeBugs("AniIDs", row.AniID, dataName .. "和" .. delayTimeName, dataName .. "和" .. delayTimeName .. "被分号分割数量不一致")
                    end

                    local key = 0
                    for data in string.gmatch(row[dataName], "([^;]+)") do
                        key = key + 1
                        containerData[key] = { [dataName] = data, DelayTime = nil }
                    end

                    key = 0
                    for delayTime in string.gmatch(row[delayTimeName], "([^;]+)") do
                        key = key + 1
                        if not string.match(delayTime, "^%d+%.?%d*$") or tonumber(delayTime) == 0 then
                            DeBugs("AniIDs", row.AniID, delayTimeName, delayTimeName .. "存在不是数值或小数点的字符或者有数值=0，应当为大于0的数值")
                        end
                        if string.find(delayTime, "%.") then
                            local minVal, mult = getMultiplierAndMinValue(delayTime)
                            minVal = 1 / minVal
                            minVal, mult = gcdAndNormalize(minVal, mult)
                            addUniqueSpeed(minVal)
                            containerData[key].DelayTime = minVal
                            containerData[key].TemporaryRecords = mult
                        else
                            containerData[key].DelayTime = tonumber(delayTime)
                        end
                    end
                end
                return containerData
            end

            -- 处理Quote和Audio
            AIDs.Quote = processQuotesAndAudios("Quote", "QuoteDelayTime", "Quote")
            AIDs.Audio = processQuotesAndAudios("Audio", "AudioDelayTime", "Audio")

            -- 计算最小公倍数
            local LCM_List = function(numbers)
                local result = numbers[1]
                for i = 2, #numbers do
                    result = result * numbers[i] / gcd(result, numbers[i])
                end
                return result
            end
            AIDs.Speed = LCM_List(SpeedTable)

            -- 设置计时器速度及每个图片切换速度
            local Clock = { 0 }
            for i = 1, key do
                AIDs.Ani[i].StopTime = AIDs.Speed / AIDs.Ani[i].StopTime
                Clock[i] = Clock[i - 1] + AIDs.Ani[i].StopTime
            end

            local setActivationPoints = function(container)
                for i = 1, #container do
                    local item = container[i]
                    if item.TemporaryRecords then
                        item.DelayTime = (AIDs.Speed / item.DelayTime) * item.TemporaryRecords
                        item.TemporaryRecords = nil
                    else
                        item.DelayTime = Clock[item.DelayTime]
                    end
                end
            end

            -- 应用到Quote和Audio设定激活点
            setActivationPoints(AIDs.Quote)
            setActivationPoints(AIDs.Audio)

            AIDs.OffsetX = aniIDRow.OffsetX
            AIDs.OffsetY = aniIDRow.OffsetY
        end
    end
end
	
--[[
function CreateAniIDs()

	for row in GameInfo.AniIDs() do
		-- 设计具体的大动画
		local AIDs = AniIDs[row.AniID]
		if AIDs then
			-- 检查Initial
            StringDeBugs2(row.Initial,"AniIDs", "AniID=" ..row.AniID,"Initial", D2)
			
			-- 处理Initial,相当于开始处理Anis表了
			-- row.Initial的值直接是对应的AniType
			local InitialAni = GameInfo.Anis[row.Initial]
			-- 因为是初始动画所以InitialAni.Loop不用管，我们不需要它循环播放
			-- 记录整个大动画所有动画片段有的速度,来选用计时器
            local SpeedTable = {};
            local function AddUniqueSpeed(Speed)
                for _, v in pairs(SpeedTable) do
                    if v == Speed then
                        return
                    end
                end
                table.insert(SpeedTable, Speed)
            end
            
			local key = 0;
			for AniClip in string.gmatch(InitialAni.AllAniClips, "([^;]+)") do
                local Clip = GameInfo.AniClips[AniClipMood(AniClip)]
				-- 拆分具体动画
				if Clip.Speed <= 0 then DeBugs("AniClips", AniClip, "Speed", "没有大于0") end

                AddUniqueSpeed(Clip.Speed)
				-- 处理TName和Num
				for i=1 Clip.Num then
					key = key + 1
					-- 真正的图片停顿的时间'StopTime'待选定计时器来在设置
					-- StopTime现在是暂存每个图片切换速度
					AIDs.Ani[key] = {
						TName = Clip.TName .."_" ..i,
						StopTime = Clip.Speed
					}
				end
			end

			-- 检查Sequence
			StringDeBugs(row.Sequence,"AniIDs", "AniID=" ..row.AniID,"Sequence,", D1 .."AniType")
			-- 处理Sequence
			-- 需要拆分出AniType
            local lastAniType = false;
			local AniTypeNum = 0;
			local AniTypeTotal = string.gsub(row.Sequence, ";", "") + 1
			for AniType in string.gmatch(row.Sequence, "([^;]+)") do
				local Ani = GameInfo.Anis[AniType]
				AniTypeNum = AniTypeNum + 1;
                if AniTypeNum == AniTypeTotal and Ani.Loop then -- 此时是最后一个 AniType,且该基础动画为循环动画
                    lastAniType = true;
                end
				for AniClip in string.gmatch(Ani.AllAniClips, "([^;]+)") do
                    local Clip = GameInfo.AniClips[AniClipMood(AniClip)]
					-- 拆分具体动画
					if Clip.Speed <= 0 then DeBugs("AniClips", AniClip, "Speed", "没有大于0") end
					
                    AddUniqueSpeed(Clip.Speed)
					-- 处理TName和Num
					for i=1 AniClip.Num then
						key = key + 1
                        if lastSequence then -- 此时是最后一个 AniType基础动画
                            lastAniType = false;
                            AIDs.LoopKey = key; --  记录最后一个基础动画的第一个图片的Key用于循环跳回到这里播放
                        end
						-- 真正的图片停顿的时间'StopTime'待选定计时器来在设置
						-- StopTime现在是暂存每个图片切换速度
						AIDs.Ani[key] = {
							Name = AniClip.TName .."_" ..i,
							StopTime = Clip.Speed
						}
					end
                end
            end

            local function getMultiplierAndMinValue(num)
                local integerPart, decimalPart = math.modf(num)
            
                -- 计算小数部分的最小单位
                local minDecimalValue = 10 ^ (-math.abs(math.log10(decimalPart)))
            
                -- 将小数转换为其最小单位的倍数
                local multiplier = (integerPart + decimalPart) * minDecimalValue
            
                return minDecimalValue, multiplier
            end
            -- 定义一个辅助函数用于计算两个数的最大公约数
            local function Gcd(x, y)
                while y ~= 0 do
                    local temp = x
                    x = y
                    y = temp % y
                end
                return x
            end
            local function gcdAndNormalize(a, b)
                -- 求a和b的最大公约数
                local greatest_common_divisor = Gcd(math.abs(a), math.abs(b))
            
                -- 返回除以最大公约数后的结果
                return a / greatest_common_divisor, b / greatest_common_divisor
            end
            --[ 处理Quote和QuoteDelayTime
            local Quote = AIDs.Quote
            if row.Quote then
                Quote = {}
                local QuoteTotal = string.gsub(row.Quote, ";", "") + 1;
                local QuoteDelayTimeTotal = string.gsub(row.QuoteDelayTime, ";", "") + 1;
                if QuoteTotal ~= QuoteDelayTimeTotal then
                    DeBugs("AniIDs", row.AniID, "Quote和QuoteDelayTime", "Quote和QuoteDelayTime被分号分割数量不一致")
                end
                local QuoteKey, QuoteDelayTimeKey = 0, 0;
                for Quote in string.gmatch(row.Quote, "([^;]+)") do
                    QuoteKey = QuoteKey + 1;
                    Quote[QuoteKey] = { Quote = Quote, DelayTime};
                end
                for QuoteDelayTime in string.gmatch(row.QuoteDelayTime, "([^;]+)") do
                    QuoteDelayTimeKey = QuoteDelayTimeKey + 1;
                    if not string.match(QuoteDelayTime, "^%d+%.?%d*$") or tonumber(QuoteDelayTime) == 0 then -- 判断字符串是否由数字和小数点组成
                        DeBugs("AniIDs", row.AniID, "QuoteDelayTime", "QuoteDelayTime存在不是数值或小数点的字符或者有数值=0，应当为大于0的数值")
                    end
                    if string.find(QuoteDelayTime, "%.") then -- 此时DelayTime为小数类型为秒计时模式
                        local minVal, mult = getMultiplierAndMinValue(QuoteDelayTime)
                        minVal = 1 / minVal; --此时这是初步计算出来的1秒切换几次的速度，在这个速度下第mult次就是QuoteDelayTime的时间
                        minVal, mult = gcdAndNormalize(minVal, mult); -- 除以小公倍数，此时就是最慢速度需求，从而实现减小计时器运算次数
                        AddUniqueSpeed(minVal) -- 记录计时器速度
                        -- DelayTime现在是暂存每个Quote切换速度,TemporaryRecords临时记录
                        Quote[QuoteDelayTimeKey].DelayTime = minVal;
                        Quote[QuoteDelayTimeKey].TemporaryRecords = mult;
                    else -- 此时DelayTime为整数类型,为图片计数模式
                        -- DelayTime现在是暂存每个Quote切换图片数
                        Quote[QuoteDelayTimeKey].DelayTime = QuoteDelayTime;
                    end
                end
            end
            -- 处理Audio和AudioDelayTime
            local Audio = AIDs.Audio
            if row.Audio then
                Audio = {}
                local AudioTotal = string.gsub(row.Audio, ";", "") + 1;
                local AudioDelayTimeTotal = string.gsub(row.AudioDelayTime, ";", "") + 1;
                if AudioTotal ~= AudioDelayTimeTotal then
                    DeBugs("AniIDs", row.AniID, "Audio和AudioDelayTime", "Audio和AudioDelayTime被分号分割数量不一致")
                end
                local AudioKey, AudioDelayTimeKey = 0, 0;
                for Audio in string.gmatch(row.Audio, "([^;]+)") do
                    AudioKey = AudioKey + 1;
                    Audio[AudioKey] = { Audio = Audio, DelayTime};
                end
                for AudioDelayTime in string.gmatch(row.AudioDelayTime, "([^;]+)") do
                    AudioDelayTimeKey = AudioDelayTimeKey + 1;
                    if not string.match(AudioDelayTime, "^%d+%.?%d*$") or tonumber(AudioDelayTime) == 0 then -- 判断字符串是否由数字和小数点组成
                        DeBugs("AniIDs", row.AniID, "AudioDelayTime", "AudioDelayTime存在不是数值或小数点的字符或者有数值=0，应当为大于0的数值")
                    end
                    if string.find(AudioDelayTime, "%.") then -- 此时DelayTime为小数类型为秒计时模式
                        local minVal, mult = getMultiplierAndMinValue(AudioDelayTime)
                        minVal = 1 / minVal; --此时这是初步计算出来的1秒切换几次的速度，在这个速度下第mult次就是AudioDelayTime的时间
                        minVal, mult = gcdAndNormalize(minVal, mult); -- 除以小公倍数，此时就是最慢速度需求，从而实现减小计时器运算次数
                        AddUniqueSpeed(minVal) -- 记录计时器速度
                        -- DelayTime现在是暂存每个Audio切换速度,TemporaryRecords临时记录
                        Audio[AudioDelayTimeKey].DelayTime = minVal;
                        Audio[AudioDelayTimeKey].TemporaryRecords = mult;
                    else -- 此时DelayTime为整数类型,为图片计数模式
                        -- DelayTime现在是暂存每个Audio切换图片数
                        Audio[AudioDelayTimeKey].DelayTime = AudioDelayTime;
                    end
                end
            end
            --]
            -- 新增处理Quote和Audio的通用函数
            local function processQuotesAndAudios(dataName, delayTimeName, container)
                local containerData = AIDs[container]

                if row[dataName] then
                    containerData = {}
                    local dataTotal = string.gsub(row[dataName], ";", "") + 1
                    local delayTimeTotal = string.gsub(row[delayTimeName], ";", "") + 1
                    if dataTotal ~= delayTimeTotal then
                        DeBugs("AniIDs", row.AniID, dataName.."和"..delayTimeName, dataName.."和"..delayTimeName.."被分号分割数量不一致")
                    end

                    local key = 0
                    for data in string.gmatch(row[dataName], "([^;]+)") do
                        key = key + 1
                        containerData[key] = { [dataName] = data, DelayTime = nil }
                    end
                    
                    key = 0 -- 重置key
                    for delayTime in string.gmatch(row[delayTimeName], "([^;]+)") do
                        key = key + 1
                        if not string.match(delayTime, "^%d+%.?%d*$") or tonumber(delayTime) == 0 then
                            DeBugs("AniIDs", row.AniID, delayTimeName, delayTimeName.."存在不是数值或小数点的字符或者有数值=0，应当为大于0的数值")
                        end
                        
                        if string.find(delayTime, "%.") then
                            local minVal, mult = getMultiplierAndMinValue(delayTime)
                            minVal = 1 / minVal
                            minVal, mult = gcdAndNormalize(minVal, mult)
                            AddUniqueSpeed(minVal)
                            containerData[key].DelayTime = minVal
                            containerData[key].TemporaryRecords = mult
                        else
                            containerData[key].DelayTime = tonumber(delayTime)
                        end
                    end
                end
                
                return containerData
            end

            
            AIDs.Quote = processQuotesAndAudios("Quote", "QuoteDelayTime", "Quote")
            AIDs.Audio = processQuotesAndAudios("Audio", "AudioDelayTime", "Audio")

            local function LCM_List(numbers) ---求表中最小公倍数函数
                local result = numbers[1]
                for i = 2, #numbers do
                    local a, b = result, numbers[i]
                    while b ~= 0 do
                        local temp = b
                        b = a % b
                        a = temp
                    end
                    result = result * numbers[i] / a
                end
                return result
            end
            -- 设定计时器速度，并保存计时器速度，以便在LeaderScene.lua使用
            local ASpeed = AIDs.Speed
            ASpeed = LCM_List(SpeedTable) -- 计时器速度为所有图片切换速度的最小公倍数，以便StopTime保持整数
            local Clock = {};
            Clock[0] = 0
            -- 设定计时器速度，并保存计时器速度，以便在LeaderScene.lua使用
            -- 设定每个图片切换速度
            for i=1 key do
                AIDs.Ani[i].StopTime = ASpeed / AIDs.Ani[i].StopTime
                Clock[i] = Clock[i-1] + AIDs.Ani[i].StopTime;
            end

            local function setActivationPoints(container)
                for i = 1, #container do
                    local item = container[i]
            
                    if item.TemporaryRecords then
                        item.DelayTime = (ASpeed / item.DelayTime) * item.TemporaryRecords
                        item.TemporaryRecords = nil
                    else
                        item.DelayTime = Clock[item.DelayTime]
                    end
                end
            end
            
            -- 应用到Quote和Audio设定激活点
            setActivationPoints(AIDs.Quote)
            setActivationPoints(AIDs.Audio)
            
            AIDs.OffsetX = row.OffsetX
            AIDs.OffsetY = row.OffsetY
        end
    end
end
--]]









